﻿using Sttplay.Transmission.TCP;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;

namespace transmission
{
    class TCPServerContext
    {
        private TCPServer server;
        private string ip;
        private int port;
        private TreeViewItem treeItem;
        private StackPanelEx stack;
        private Image icon;
        private Dictionary<Socket, TCPClientContext> clients = new Dictionary<Socket, TCPClientContext>();
        public bool IsRun { get; private set; }
        public TCPServerContext(string ip, int port, bool isPacket)
        {
            this.ip = ip;
            this.port = port;
            server = new TCPServer(isPacket);
            server.onClientConnectEvent += OnClientConnected;
            server.onClientDisconnectEvent += OnClientDisconnected;
            server.onClientRecvEvent += OnClientRecv;

            treeItem = new TreeViewItem();
            treeItem.IsExpanded = true;
            stack = new StackPanelEx();
            stack.Orientation = Orientation.Horizontal;
            treeItem.Header = stack;
            icon = new Image();
            icon.VerticalAlignment = VerticalAlignment.Center;
            icon.Height = 15;
            icon.Width = 15;
            icon.Margin = new Thickness(0, 0, 4, 0);
            icon.Source = new BitmapImage(new Uri("pack://application:,,,/res/server_run.png"));
            stack.Children.Add(icon);
            TextBlock textBlock = new TextBlock();
            textBlock.VerticalAlignment = VerticalAlignment.Center;
            textBlock.Text = string.Format("{0}:{1}", ip, port);
            stack.Children.Add(textBlock);
            treeItem.IsSelected = true;
            stack.user = this;
            stack.type = TransmissionType.TcpServer;
        }

        public bool InitializeServer()
        {
            if (!server.Initialize(System.Net.IPAddress.Parse(ip), port))
            {
                Release();
                return false;
            }
            IsRun = true;
            icon.Source = new BitmapImage(new Uri("pack://application:,,,/res/server_run.png"));
            return true;
        }

        private void OnClientRecv(TCPClient proxy, byte[] buffer)
        {
            if (clients.ContainsKey(proxy.Socket))
                clients[proxy.Socket].OnRecv(buffer);
        }

        private void OnClientDisconnected(TCPClient proxy)
        {
            if (clients.ContainsKey(proxy.Socket))
            {
                clients[proxy.Socket].GetTreeViewItem().PreviewMouseDown -= MainWindow.Instance.OnTreeBtnClicked;
                treeItem.Items.Remove(clients[proxy.Socket].GetTreeViewItem());
                clients.Remove(proxy.Socket);
                if (MainWindow.Instance.topSelect == "TCP Server")
                    MainWindow.Instance.OnTreeBtnClicked(treeItem, null);
            }
        }

        public void OnManualClose(TCPClientContext context)
        {
            TCPClient proxy = context.GetProxy();
            clients.Remove(context.GetProxy().Socket);
            treeItem.Items.Remove(context.GetTreeViewItem());
            server.DisconnectClient(proxy);
        }

        private void OnClientConnected(TCPClient proxy)
        {
            TCPClientContext context = new TCPClientContext(proxy, "", 0, true);
            clients.Add(proxy.Socket, context);
            treeItem.Items.Add(context.GetTreeViewItem());
            context.GetTreeViewItem().PreviewMouseDown += MainWindow.Instance.OnTreeBtnClicked;
            if(MainWindow.Instance.topSelect == "TCP Server")
                MainWindow.Instance.OnTreeBtnClicked(context.GetTreeViewItem(), null);
            else
            {
                MainWindow.Instance.OnTreeBtnClicked(MainWindow.Instance.selectItem, null);
                MainWindow.Instance.selectItem.IsSelected = true;
            }
        }

        public void Update()
        {
            foreach (var item in clients)
            {
                item.Value.Update();
            }
            server.Update();
        }

        public TreeViewItem GetTreeViewItem()
        {
            return treeItem;
        }

        public string GetIP()
        {
            return ip;
        }

        public int GetPort()
        {
            return port;
        }

        public void Release()
        {
            treeItem.Items.Clear();
            server.Terminate();
            clients.Clear();
            IsRun = false;
            icon.Source = new BitmapImage(new Uri("pack://application:,,,/res/server_stop.png"));
        }
    }
}
